package com.laamella.syntherface.shell;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.sound.midi.MidiDevice;
import javax.sound.midi.MidiUnavailableException;
import javax.swing.ButtonGroup;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;

import com.laamella.syntherface.midi.MidiHandler;
import com.laamella.syntherface.synths.Syntherface;
import com.laamella.syntherface.synths.events.EventListener;
import com.laamella.syntherface.synths.events.SynthWideEvents;
import com.laamella.syntherface.synths.midi.MidiInterface;
import com.laamella.syntherface.synths.models.ParameterModel;
import java.util.ArrayList;
import java.util.List;

@SuppressWarnings("serial") public class SyntherfaceFrame extends javax.swing.JFrame {

	public final MidiInterface midiInterface;
	public JPanel synthEditPanel;
	private Syntherface syntherface;
	private final List<ParameterModel> masterParameterList=new ArrayList<ParameterModel>();

	/** Creates new form SyntherfaceFrame */
	public SyntherfaceFrame() {
		SynthWideEvents.newParameterRegistered().listeners.add(new EventListener<ParameterModel>(){
			public void onEvent(ParameterModel parameter) {
				masterParameterList.add(parameter);
			}
		});

		midiInterface = new MidiInterface();
		// TODO currently just picks the first synth
		syntherface = CrapPluginList.synthRegistry.get(0);
		synthEditPanel = syntherface.constructSyntherface(midiInterface);
		initComponents();
		populateMidiDeviceMenus();
	}

	/**
	 * This method is called from within the constructor to initialize the
	 * form. WARNING: Do NOT modify this code. The content of this method is
	 * always regenerated by the Form Editor.
	 */
	@SuppressWarnings("unchecked")// <editor-fold defaultstate="collapsed"
	// desc="Generated
	// <editor-fold defaultstate="collapsed" desc="Generated
	// <editor-fold defaultstate="collapsed" desc="Generated
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jScrollPane1 = new javax.swing.JScrollPane();
        editPanel1 = synthEditPanel;
        statusBarPanel1 = new com.laamella.syntherface.shell.StatusBarPanel();
        jMenuBar1 = new javax.swing.JMenuBar();
        fileMenu = new javax.swing.JMenu();
        newWindowMenuItem = new javax.swing.JMenuItem();
        exitMenuItem = new javax.swing.JMenuItem();
        editMenu = new javax.swing.JMenu();
        refreshMidiHandlerMenuItem = new javax.swing.JMenuItem();
        sendParametersToSynthesizerMenuItem = new javax.swing.JMenuItem();
        randomizeParametersMenuItem = new javax.swing.JMenuItem();
        receivePatchMenuItem = new javax.swing.JMenuItem();
        sendPatchMenuItem = new javax.swing.JMenuItem();
        synthesizerTypeMenu = new javax.swing.JMenu();
        jMenu5 = new javax.swing.JMenu();
        jMenuItem2 = new javax.swing.JMenuItem();
        jMenu6 = new javax.swing.JMenu();
        jMenuItem4 = new javax.swing.JMenuItem();
        midiReceiverMenu = new javax.swing.JMenu();
        midiTransmitterMenu = new javax.swing.JMenu();
        helpMenu = new javax.swing.JMenu();
        helpOnSynthesizerMenuItem = new javax.swing.JMenuItem();
        helpAboutMenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("Syntherface 1.0");
        setName("mainFrame"); // NOI18N
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jScrollPane1.setBorder(null);

        editPanel1.setPreferredSize(new java.awt.Dimension(2000, 1500));
        jScrollPane1.setViewportView(editPanel1);

        getContentPane().add(jScrollPane1, java.awt.BorderLayout.CENTER);
        getContentPane().add(statusBarPanel1, java.awt.BorderLayout.PAGE_END);

        fileMenu.setText("File");

        newWindowMenuItem.setText("New window");
        fileMenu.add(newWindowMenuItem);

        exitMenuItem.setText("Exit");
        fileMenu.add(exitMenuItem);

        jMenuBar1.add(fileMenu);

        editMenu.setText("Edit");

        refreshMidiHandlerMenuItem.setText("Refresh Midi receivers & transmitters");
        refreshMidiHandlerMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                refreshMidiHandlerMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(refreshMidiHandlerMenuItem);

        sendParametersToSynthesizerMenuItem.setText("Send all parameters to synthesizer");
        sendParametersToSynthesizerMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                sendParametersToSynthesizerMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(sendParametersToSynthesizerMenuItem);

        randomizeParametersMenuItem.setText("Randomize all parameters");
        randomizeParametersMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                randomizeParametersMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(randomizeParametersMenuItem);

        receivePatchMenuItem.setText("Receive patch");
        receivePatchMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                receivePatchMenuItemActionPerformed(evt);
            }
        });
        editMenu.add(receivePatchMenuItem);

        sendPatchMenuItem.setText("Send patch");
        sendPatchMenuItem.setEnabled(false);
        editMenu.add(sendPatchMenuItem);

        jMenuBar1.add(editMenu);

        synthesizerTypeMenu.setText("Synthesizer type");

        jMenu5.setText("Alesis");

        jMenuItem2.setText("Micron");
        jMenu5.add(jMenuItem2);

        synthesizerTypeMenu.add(jMenu5);

        jMenu6.setText("Yamaha");

        jMenuItem4.setText("TG55");
        jMenu6.add(jMenuItem4);

        synthesizerTypeMenu.add(jMenu6);

        jMenuBar1.add(synthesizerTypeMenu);

        midiReceiverMenu.setText("Midi receiver");
        jMenuBar1.add(midiReceiverMenu);

        midiTransmitterMenu.setText("Midi transmitter");
        jMenuBar1.add(midiTransmitterMenu);

        helpMenu.setText("Help");

        helpOnSynthesizerMenuItem.setText("Synthesizer");
        helpOnSynthesizerMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                helpOnSynthesizerMenuItemActionPerformed(evt);
            }
        });
        helpMenu.add(helpOnSynthesizerMenuItem);

        helpAboutMenuItem.setText("About");
        helpAboutMenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                helpAboutMenuItemActionPerformed(evt);
            }
        });
        helpMenu.add(helpAboutMenuItem);

        jMenuBar1.add(helpMenu);

        setJMenuBar(jMenuBar1);

        pack();
    }// </editor-fold>//GEN-END:initComponents

private void receivePatchMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_receivePatchMenuItemActionPerformed
try {
	syntherface.receivePatch();
} catch (Exception e) {
	SynthWideEvents.statusUpdate().send(e.getMessage());
}
}//GEN-LAST:event_receivePatchMenuItemActionPerformed

private void helpOnSynthesizerMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_helpOnSynthesizerMenuItemActionPerformed
	syntherface.help();
}//GEN-LAST:event_helpOnSynthesizerMenuItemActionPerformed

private void sendParametersToSynthesizerMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_sendParametersToSynthesizerMenuItemActionPerformed
	for(ParameterModel parameter: masterParameterList){
		parameter.sendToSynthesizer();
	}
	SynthWideEvents.statusUpdate().send("Up to date!");
	
}//GEN-LAST:event_sendParametersToSynthesizerMenuItemActionPerformed

private void randomizeParametersMenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_randomizeParametersMenuItemActionPerformed
	for(ParameterModel parameter: masterParameterList){
		parameter.setValue((int)(parameter.getMinimum()+Math.random()*(parameter.getMaximum()-parameter.getMinimum())));
	}
	SynthWideEvents.statusUpdate().send("Randomized!");
}//GEN-LAST:event_randomizeParametersMenuItemActionPerformed

	private void helpAboutMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_jMenuItem3ActionPerformed

		
	}// GEN-LAST:event_jMenuItem3ActionPerformed

	private void populateMidiDeviceMenus() {
		ButtonGroup transmitterGroup = new ButtonGroup();
		ButtonGroup receiverGroup = new ButtonGroup();
		try {
			midiReceiverMenu.removeAll();
			for (final MidiDevice.Info info : MidiHandler.midiHandler.receivers) {
				final String name = info.getName() == null ? "null" : info.getName();
				JRadioButtonMenuItem item = new JRadioButtonMenuItem(name);
				item.addActionListener(new ActionListener() {

					@Override public void actionPerformed(ActionEvent arg0) {
						try {
							midiInterface.openReceiver(info);
						} catch (MidiUnavailableException e) {
							e.printStackTrace();
						}
					}
				});
				receiverGroup.add(item);
				midiReceiverMenu.add(item);
				if (name.contains("USB")) {
					item.doClick();
				}
			}

			midiTransmitterMenu.removeAll();
			for (final MidiDevice.Info info : MidiHandler.midiHandler.transmitters) {
				final String name = info.getName() == null ? "null" : info.getName();
				JRadioButtonMenuItem item = new JRadioButtonMenuItem(name);
				item.addActionListener(new ActionListener() {

					@Override public void actionPerformed(ActionEvent arg0) {
						try {
							midiInterface.openTransmitter(info);
						} catch (MidiUnavailableException e) {
							e.printStackTrace();
						}
					}
				});
				transmitterGroup.add(item);
				midiTransmitterMenu.add(item);
				if (name.contains("USB")) {
					item.doClick();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void refreshMidiHandlerMenuItemActionPerformed(java.awt.event.ActionEvent evt) {// GEN-FIRST:event_propertiesMenuItemActionPerformed
		midiInterface.closeAll();
		MidiHandler.midiHandler.refresh();
		populateMidiDeviceMenus();
	}// GEN-LAST:event_propertiesMenuItemActionPerformed

	private void formWindowClosing(java.awt.event.WindowEvent evt) {// GEN-FIRST:event_formWindowClosing

		if (midiInterface != null) {
			midiInterface.closeAll();
		}

	}// GEN-LAST:event_formWindowClosing

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenu editMenu;
    private javax.swing.JPanel editPanel1;
    private javax.swing.JMenuItem exitMenuItem;
    private javax.swing.JMenu fileMenu;
    private javax.swing.JMenuItem helpAboutMenuItem;
    private javax.swing.JMenu helpMenu;
    private javax.swing.JMenuItem helpOnSynthesizerMenuItem;
    private javax.swing.JMenu jMenu5;
    private javax.swing.JMenu jMenu6;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem2;
    private javax.swing.JMenuItem jMenuItem4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JMenu midiReceiverMenu;
    private javax.swing.JMenu midiTransmitterMenu;
    private javax.swing.JMenuItem newWindowMenuItem;
    private javax.swing.JMenuItem randomizeParametersMenuItem;
    private javax.swing.JMenuItem receivePatchMenuItem;
    private javax.swing.JMenuItem refreshMidiHandlerMenuItem;
    private javax.swing.JMenuItem sendParametersToSynthesizerMenuItem;
    private javax.swing.JMenuItem sendPatchMenuItem;
    private com.laamella.syntherface.shell.StatusBarPanel statusBarPanel1;
    private javax.swing.JMenu synthesizerTypeMenu;
    // End of variables declaration//GEN-END:variables
	public static void startGui() {
		try {
			javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (Exception e) {
			e.printStackTrace();
		}
		java.awt.EventQueue.invokeLater(new Runnable() {

			public void run() {
				new SyntherfaceFrame().setVisible(true);
			}
		});

	}
}
